//----------------------------------------------------------------------------------------------------------------
//			Filename:		RayTracing.cpp
//			  Author:		Adrian De Barro
//			    Date:		12/08/2015
//----------------------------------------------------------------------------------------------------------------
//			  Status: REFACTORING
//----------------------------------------------------------------------------------------------------------------
#include "stdafx.h"


#include <winsock2.h>
#include <vector>
#include <chrono>
#include <string>

#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost\program_options.hpp>

#include "Integrators/RadianceDetails/RadiancePoint.h"
#include "World\AbstractWorld.h"
#include "World\SingleThreadWorld.h"
#include "World\MultiThreadedWorld.h"
#include "CoreClasses\GeometricObjects\GeometricObjects.h"
#include "CoreClasses\GeometricObjects\Objects.h"
#include "CoreClasses\Point\Point3D\Point3D.h"
#include "CoreClasses\UtilClasses\Common.h"
#include "CoreClasses\Logger\Logger.h"
#include "CoreClasses\Camera\Camera.h"
#include "GuiHelper\gw.h"
#include "CoreClasses\Camera\Camera.h"
#include "CoreClasses\Image Representation\ImageSaver\ImageSaver.h"
#include "Networking/PeerInitializer/PeerInitializer.h"
#include "Integrators/RadianceDetails/RadiancePoint.h"
#include "Networking/ObservableEventsList/ICObservableEventsList.h"
#include "Integrators/IrradianceCache.h"
#include "Networking/ObservableEvents/InsertEvent.h"
#include "Networking/ObservableEventsList/ICObservableEventsList.h"
#include "CoreClasses/Camera/Paths/Checkpoints/Checkpoints.h"
#include "CoreClasses/Logger/SnapshotExtracter.h"
#include "CoreClasses\Camera\Paths\RandomPathGenerator\RandomPathGenerator.h"

#include "Networking\ObservableEventsList\ICObservableEventsList.h"
#include "Networking\ObservableEvents\InsertEvent.h"


#define SCRWIDTH	600
#define SCRHEIGHT	600
#define SCENE_TYPE 9

#define CAMERA_DELTA 0.5
#define AMOUNT_FRAMES_TOTAL 100
#define VIEW_PLANE_EYE_DISTANCE 1
#define MULTIPLE_FRAMES
#define PATH_AVAILABLE
#define ON_NETWORK

//#define BOOST_ALL_DYN_LINK

#include <Peer/PeerTestingFramework/PeerTestingFramework.h>


typedef boost::shared_mutex Lock;
typedef boost::unique_lock< Lock > WriteLock;
typedef boost::shared_lock< Lock > ReadLock;


using namespace Engine::Networking;
using namespace Engine;
using namespace Engine::Logs;

namespace po = boost::program_options;

//
//int main(int argc, char* argv[])
//{
//	Network::Communication::TestClient tester();
//	system("pause");
//}

int amountOfPeers = 5;
int peerIndex = 0;
string startupIpAddress = "";
int pathNumber = 0;
string outputFileName = "";
float deltaIntervalBenchmarks = 0.5f;
int useNetwork = 0;
int socketNumber = 0;
string peerName = "";
int sceneType = 0;
int windowSize = 0;
int numberThreads = 0;
int gateKeeper = 1;
long fltFailedCommTm = 0.5;
long fltSleepAfterCommTm = 0.25;
string ipAddress = "";
int useRandomPath = 0;
string pathConfigFile = "";


//----------------------------------------------------------------------------------------------------------------
// Method Name: CONSTRUCTOR Return Value: VOID
//  Parameters: int argc, char* argv[]
//   Status: READY. 
//----------------------------------------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
	////Engine::AbstractWorld * currentWorld = new Engine::SingleThreadWorld(SCENE_TYPE, SCRWIDTH, SCRHEIGHT);

	po::options_description desc("Allowed options");

	//adding allowed parameters
	desc.add_options()
		("help", "This is a pre alpha testing prototype")
		("amountPeers", po::value<int>(),"Amount of peers to be expected on network")
		("peerIndex", po::value<int>(), "Peer index in the whole affair")
		("gatekeeperIp", po::value<string>(), "Ip address of the first peer to communicate with")
		("pathNumber", po::value<int>(), "Path number to use for render")
		("outputFileName", po::value<string>(), "Data Saver file name")
		("intervalForBenchmark", po::value<float>(), "Delta for taking data")
		("timeAfterCommAtempt", po::value<float>(), "Time to wait before reattempting to connect with another peer in seconds")
		("timeSleepAfterFailedAttempt", po::value<float>(), "Time to wait after communication attempt failed, in seconds")
		("useNetwork", po::value<int>(), "Variable to use the network or not")
		("socketNumber", po::value<int>(), "Socket number for listening on the network")
		("gateKeeper", po::value<int>(), "Make instance a gate keeper")
		("peerName", po::value<string>(), "Name of the instance")
		("sceneType", po::value<int>(), "Scene to be rendered")
		("windowSize", po::value<int>(), "Size of screen window")
		//amount of threads as workers
		("mt", po::value<int>(), "Number of threads")
		//ipaddress  or Randomkey to use for random seed
		("ipAddress", po::value<string>(), "Ip Address used only for random seed")
		//if to use random path
		("useRandomPath", po::value<int>(), "1 to use random path and no for not using a random path")
		//path to the config file
		("pathConfigFile", po::value<string>(), "Specify if you are using a random path")
	;


	po::options_description hidden("Hidden options");
	
	hidden.add_options()
		("configInputFile", po::value<string>(), "Input file containing the configuration")
		;


	po::options_description cmdlineOptions;
	cmdlineOptions.add(desc).add(hidden);
	try
	{
		po::variables_map vm;

		
		po::store(po::parse_command_line(argc, argv, cmdlineOptions), vm);
		

		if (vm.count("configInputFile"))
		{
			ifstream ifs(vm["configInputFile"].as<string>());
			if (!ifs)
			{
				cout << "Command line path is invalid" << endl;
				system("pause");
				return 0;
			}
			else
			{
				po::store(po::parse_config_file(ifs, desc), vm);
				po::notify(vm);
			}
		}

		try
		{
			if (vm.count("help"))
			{
				cout << desc << endl;
				system("pause");
				return 0;
			}

			if (vm.count("amountPeers"))
			{
				amountOfPeers = vm["amountPeers"].as<int>();
			}

			if (vm.count("peerIndex"))
			{
				peerIndex = vm["peerIndex"].as<int>();
			}

			if (vm.count("gatekeeperIp"))
			{
				startupIpAddress = vm["gatekeeperIp"].as<string>();
			}
			else
			{
				startupIpAddress = "123.0.0.5";
			}

			if (vm.count("pathNumber"))
			{
				pathNumber = vm["pathNumber"].as<int>();
			}
			else
			{
				pathNumber = 0;
			}

			if (vm.count("outputFileName"))
			{
				outputFileName = vm["outputFileName"].as<string>();
			}
			else
			{
				outputFileName = "";
			}

			if (vm.count("intervalBenchmark"))
			{
				deltaIntervalBenchmarks = vm["intervalBenchmark"].as<float>();
			}
			else
			{
				deltaIntervalBenchmarks = 0.5f;
			}

			if (vm.count("useNetwork"))
			{
				useNetwork = vm["useNetwork"].as<int>();
			}
			else
			{
				useNetwork = 1;
			}

			if (vm.count("socketNumber"))
			{
				socketNumber = vm["socketNumber"].as<int>();
			}
			else
			{
				socketNumber = 0;
			}

			if (vm.count("peerName"))
			{
				peerName = vm["peerName"].as<string>();
			}
			else
			{
				peerName = "peer";
			}

			if (vm.count("sceneType"))
			{
				sceneType = vm["sceneType"].as<int>();
			}
			else
			{
				sceneType = 7;
			}

			if (vm.count("windowSize"))
			{
				windowSize = vm["windowSize"].as<int>();
			}
			else
			{
				windowSize = 600;
			}

			if (vm.count("mt"))
			{
				numberThreads = vm["mt"].as<int>();
			}
			else
			{
				numberThreads = 7;
			}

			if (vm.count("gateKeeper"))
			{
				gateKeeper = vm["gateKeeper"].as<int>();
			}
			else
			{
				gateKeeper = 1;
			}

			if (vm.count("timeAfterCommAtempt"))
			{
				fltFailedCommTm = vm["timeAfterCommAtempt"].as<float>();
			}

			if (vm.count("timeSleepAfterFailedAttempt"))
			{
				fltSleepAfterCommTm = vm["timeSleepAfterFailedAttempt"].as<float>();
			}

			if (vm.count("ipAddress"))
			{
				ipAddress = vm["ipAddress"].as<string>(); 

			}

			if (vm.count("useRandomPath"))
			{
				useRandomPath = vm["useRandomPath"].as<int>();
			}
			else
			{
				useRandomPath = 0;
			}


			if (vm.count("pathConfigFile"))
			{
				pathConfigFile = vm["pathConfigFile"].as<string>();
			}

		}
		catch (exception e)
		{
			cout << "Error occured while parsing the file " << endl;
		}

		if (gateKeeper == 0)
		{
			//acts as a gate keeper
			Network::Peer::AbstarctPeer<string, IrradianceCache>* testPeer = new Network::Peer::P2pPeer<string, IrradianceCache>();
			system("pause");
		}
		else

		{		
			#undef ELPP_HANDLE_SIGABRT

			Engine::AbstractWorld * currentWorld = new Engine::MultiThreadWorld(sceneType, windowSize, windowSize, numberThreads);

			if (useNetwork == 1)
			{
				P2pPeer<Engine::RadiancePoint, IrradianceCache>* currentPeer;
				try
				{
					bool firstTime = false;
					gwOpen("Test Window", windowSize, windowSize);
					//currentWorld->Build(pathNumber);

					cout << startupIpAddress << endl;

					if (useRandomPath == 0)
					{
						currentWorld->Build(pathNumber);
					}
					else if (useRandomPath > 0)
					{
						_ASSERT(useRandomPath == 1 && pathConfigFile != "");
						currentWorld->Build(ipAddress, pathConfigFile);
					}

					PeerInitializer<RadiancePoint, IrradianceCache>* initPeer = new PeerInitializer<RadiancePoint, IrradianceCache>();
					AbstarctPeer<RadiancePoint, IrradianceCache>* myPeer = initPeer->InitializePeer(amountOfPeers, startupIpAddress, socketNumber, peerIndex, peerName, peerIndex, currentWorld->GetIrradainceCache(), fltSleepAfterCommTm, fltFailedCommTm);
					SnapShotExtracter* snapshotTaker = new SnapShotExtracter(currentWorld->GetIrradainceCache(), currentWorld->GetCamera());
					Engine::VidSaver saver(windowSize, windowSize, currentWorld->GetScene()->GetSceneName(), currentWorld->GetRgbBuffer());
					

				#ifdef MULTIPLE_FRAMES
					int index = 0;

					clock_t fullStartTime = clock();
					clock_t fullEndTime;

					while (currentWorld->CheckIfMoreFrames())
					{
						clock_t startTime = clock();
						Engine::Logger::LogInfo("New Frame");
						while (!currentWorld->RenderScene())
						{
							gwDoEvents();
							this_thread::sleep_for(std::chrono::milliseconds(1500));
						}

						clock_t endTime = clock();
						double timeInSeconds = ((double)endTime - startTime) / (double)CLOCKS_PER_SEC;

						Engine::Logger::LogTrace("time taken is equal to-> " + to_string(timeInSeconds));
						Engine::Logger::LogTrace("Frame Ready " + index);
						currentWorld->SetCurrentY(0);
						saver.SaveFrame();
						Engine::Logger::LogInfo("ready after saving");

					#ifdef PATH_AVAILABLE
						currentWorld->MoveCamera();
					#endif
					}

					fullEndTime = clock();

					double timeInSeconds = ((double)fullEndTime - fullStartTime) / (double)CLOCKS_PER_SEC;

					cout << "Time Taken is " << timeInSeconds << endl;

					myPeer->Exitlistening();
					#else
						clock_t startTime = clock();

						//while (!currentWorld->render_scene())
						while (!currentWorld->RenderScene())
						{
							gwDoEvents();
							this_thread::sleep_for(std::chrono::milliseconds(500));
						}
						clock_t endTime = clock();
						double timeInSeconds = ((double)endTime - startTime) / (double)CLOCKS_PER_SEC;
						Engine::Logger::LogTrace("time taken is equal to-> " + to_string(timeInSeconds));
						currentWorld->SetCurrentY(0);
						saver.SaveFrame();
					#endif
				}
				catch (exception e)
				{
					string outputException = e.what();
					Engine::Logger::LogError(outputException);
					CloseWindow();
				}

				Engine::Logger::LogInfo("Render Ready");

				std::system("pause");
				CloseWindow();
				delete currentWorld;
				return 0;
			}
			else
			{
				bool firstTime = false;
				gwOpen("Test Window", windowSize, windowSize);
				currentWorld->Build(pathNumber);
				Engine::VidSaver saver(windowSize, windowSize, currentWorld->GetScene()->GetSceneName(), currentWorld->GetRgbBuffer());
				int index = 0;

#ifdef MULTIPLE_FRAMES
				clock_t fullStartTime = clock();
				clock_t fullEndTime;
				while (currentWorld->CheckIfMoreFrames())
				{
					clock_t startTime = clock();
					Engine::Logger::LogInfo("New Frame");
					while (!currentWorld->RenderScene())
					{
						gwDoEvents();
						this_thread::sleep_for(std::chrono::milliseconds(1500));
					}
					clock_t endTime = clock();
					double timeInSeconds = ((double)endTime - startTime) / (double)CLOCKS_PER_SEC;

					Engine::Logger::LogTrace("time taken is equal to-> " + to_string(timeInSeconds));
					Engine::Logger::LogTrace("Frame Ready " + index);
					currentWorld->SetCurrentY(0);
					saver.SaveFrame();
					Engine::Logger::LogInfo("ready after saving");

			#ifdef PATH_AVAILABLE
				currentWorld->MoveCamera();
			#endif
				}
				fullEndTime = clock();

				double timeInSeconds = ((double)fullEndTime - fullStartTime) / (double)CLOCKS_PER_SEC;

				cout << "Time Taken is " << timeInSeconds << endl;

			#else
				clock_t startTime = clock();

				//while (!currentWorld->render_scene())
				while (!currentWorld->RenderScene())
				{
					gwDoEvents();
					this_thread::sleep_for(std::chrono::milliseconds(500));
				}
				clock_t endTime = clock();
				double timeInSeconds = ((double)endTime - startTime) / (double)CLOCKS_PER_SEC;
				Engine::Logger::LogTrace("time taken is equal to-> " + to_string(timeInSeconds));
				currentWorld->SetCurrentY(0);
				saver.SaveFrame();
			#endif

				Engine::Logger::LogInfo("Render Ready");

				std::system("pause");
				CloseWindow();
				delete currentWorld;
				return 0;
			}
		}
	}
	catch (exception ex)
	{
		cout << ex.what() << endl;
		return 0;
	}
}
/////

///-------------------------------------------------------------------------------------------------
/// <summary>	A macro that defines boost test module. </summary>
///
/// <remarks>	Adrian, 30/09/2015. </remarks>
///-------------------------------------------------------------------------------------------------
#define BOOST_TEST_MODULE MyTest
#include <algorithm>
#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test_suite.hpp>
#include <boost/test/unit_test_log.hpp>



using namespace Network::Peer;

//BOOST_AUTO_TEST_CASE(PathTestCase)
//{
//	Point3D testPoint(1, 1, 1);
//	vector<unsigned char> result;
//
//	testPoint.SerializePoint(result);
//
//
//
//
//	Point3D testPoint2(2);
//	testPoint2.FromSerialize(result);
//
//	BOOST_CHECK(testPoint == testPoint2);
//	
//	testPoint = Point3D(0.5f , 0.5f, 1);
//	result = vector<unsigned char>();
//
//	testPoint.SerializePoint(result);
//
//	testPoint2= Point3D(7);
//	testPoint2.FromSerialize(result);
//
//
//	BOOST_CHECK(testPoint == testPoint2);
//
//	RGBColor color(0.2, 0.3 ,0.99);
//	
//	RGBColor color2;
//
//	vector<unsigned char> toOutput;
//
//	color.SerializePoint(toOutput);
//
//	color2.FromSerialize(toOutput);
//
//	BOOST_CHECK(color == color2);
//
//	RadiancePoint point(Point3D(0.2,0.3,0.4), Point3D(0.5,0.6,0.7));
//	point.m_rayLength = 7;
//	point.radiance = RGBColor(0.2, 0.3, 0.4);
//
//	toOutput = vector<unsigned char>();
//	point.SerializePoint(toOutput);
//
//
//	RadiancePoint pointTest(Point3D(0), Point3D(0));
//	pointTest.FromSerialize(toOutput);
//
//	//testing at starting point 
//
//	toOutput = vector<unsigned char>();
//
//	
//
//	RadiancePoint* currentPoint= new  RadiancePoint(Point3D(0.2, 0.3, 0.4), Point3D(0.5, 0.6, 0.7));
//	currentPoint->m_rayLength = 7;
//	currentPoint->radiance = RGBColor(0.2, 0.3, 0.4);
//
//	toOutput = vector<unsigned char>();
//	ConvertionClass::ConvertInt(5, toOutput);
//	currentPoint->SerializePoint(toOutput);
//
//
//	RadiancePoint pointTest2(Point3D(0), Point3D(0));
//	pointTest2.FromSerialize(toOutput,4);
//
//	VectorTimer* currentTimer = new FixedVectorTimer(1, "5,5,5,5,5");
//	toOutput = vector<unsigned char>();
//
//	currentTimer->Serialize(toOutput);
//
//	VectorTimer* nextTimer = new FixedVectorTimer();
//	nextTimer->FromByteArray(toOutput,0);
//
//	//Network::ObservableEvents::ObservableEventsList* observableEventList = new Engine::Networking::ObservableEvents::ICObservableEventsList();
//	toOutput = vector<unsigned char>();
//	ObservableEvent<RadiancePoint, IrradianceCache>* p_observableEvent = new Engine::Networking::ObservableEvents::InsertEvent<RadiancePoint, IrradianceCache>();
//	p_observableEvent->SetTimeStamp(nextTimer);
//	p_observableEvent->SetEpoch(5);
//	for (int index = 0; index < 100; index++)
//	{
//		p_observableEvent->InsertPoint(currentPoint);
//	}
//	cout << p_observableEvent->GetUuid() << endl;
//	p_observableEvent->ToSerialize(toOutput);
//
//	ObservableEvent<RadiancePoint, IrradianceCache>* nextEvent = new Engine::Networking::ObservableEvents::InsertEvent<RadiancePoint, IrradianceCache>();
//	nextEvent->FromSerialize(toOutput,0);
//
//	//ObservableEvent<RadiancePoint, IrradianceCache>* nextEvent2 = new Engine::Networking::ObservableEvents::InsertEvent<RadiancePoint, IrradianceCache>();
//	//nextEvent2->FromSerialize(toOutput);
//
//	ObservableEventsList<RadiancePoint, IrradianceCache>* testObservableEventList = new Engine::Networking::ObservableEvents::ICObservableEventsList();
//	testObservableEventList->SetVectorTimer(new FixedVectorTimer("1,2,3,4,5"));
//
//	//testing observable event list
//
//	for (int index = 0; index < 50; index++)
//	{
//		testObservableEventList->AddEventToList(nextEvent);
//	}
//
//	toOutput = vector<unsigned char>();
//
//	testObservableEventList->SerializeAllUuids(toOutput);
//
//	vector<uuid> toCheck = testObservableEventList->ParseByteArrayToUuids(toOutput);
//
//	vector<unsigned char> allSamplesData;
//
//	testObservableEventList->GetNeededOE(toOutput, allSamplesData);
//
//
//	ObservableEventsList<RadiancePoint, IrradianceCache>* testObservableEventList2 = new Engine::Networking::ObservableEvents::ICObservableEventsList();
//	testObservableEventList2->SetVectorTimer(new FixedVectorTimer("1,1,1,1,1"));
//
//	testObservableEventList2->MergeEvents(allSamplesData);
//	
//
//  	system("pause");
//}


/// <summary>
/// Main entry-point for this application.
/// </summary>
/// <param name="arg">Number of command-line arguments.</param>
/// <param name="argv">Array of command-line argument strings.</param>
/// <returns>
/// Exit-code for the process - 0 for success, else an error code.
/// </returns>
/// <remarks>
/// Adrian, 31/08/2015.
/// </remarks>
/// -------------------------------------------------------------------------------------------------
/// -------------------------------------------------------------------------------------------------

/*
--------------------------------------
Testing Peer neighbour handling
--------------------------------------
*/

//using namespace Network::Peer;
//using namespace RakNet;
//
//BOOST_AUTO_TEST_CASE(PathTestCase)
//{
//	vector<Checkpoint*> checkPoints;
//
//	checkPoints.push_back(new Checkpoint(Point3D(2.3, -5, -91),0));
//	checkPoints.push_back(new Checkpoint(Point3D(2.3, -5, -80),0));
//	checkPoints.push_back(new Checkpoint(Point3D(-5, -5, -80), 270));
//
//	CameraPaths* cameraPaths = new LagrangeInterpolation(checkPoints, "Test Path", 0.7);
//
//}

BOOST_AUTO_TEST_CASE(My_Test)
{
	/*Point3D test1(-0.1,0,-0.9);
	Point3D test2(1,0,0);
	float dotProduct = test1.dot(test2);
	cout << dotProduct << endl;
	*/
	CameraPaths* path = new Engine::Paths::RandomPaths("PathCheckpoints/TownCheckPointsConfig.txt", "111.222.33.556"); 

	//vector<Checkpoint*> allPoints;
	//allPoints.push_back(new Checkpoint(Point3D(0,0,0)));
	//allPoints.push_back(new Checkpoint(Point3D(0, 0, 1)));
	//allPoints.push_back(new Checkpoint(Point3D(1, 0, 1)));


	//CameraPaths* testPath = new Engine::Paths::RandomPaths();

	//testPath->ComputeCrumbles(allPoints);


	system("pause");
}




//BOOST_AUTO_TEST_CASE(My_Test)
//{
//	NeighbourManager* manager = new NeighbourManager();
//	std::string inputNeighbours = "11223-127.0.0.1|21112-0;112356-124.0.0.12|2115-0;11223-127.0.0.1|21112-0;";
//	manager->AddNewNeighbours(inputNeighbours);
//	/*testing neighbours size == 2*/
//	BOOST_CHECK(manager->GetAmountPeers() == 2);
//	std::string toFind = "127.0.0.1|21112";
//	int loc = 0;
//	BOOST_CHECK(manager->FindNeighbour(SystemAddress(toFind.c_str())) == true);
//	manager->RemoveNeighbour(SystemAddress(toFind.c_str()));
//	BOOST_CHECK(manager->FindNeighbour(SystemAddress(toFind.c_str())) == false);
//
//	Neighbour* randomNeighbor = nullptr;
//	randomNeighbor = manager->GetRandomNeighbour();
//	BOOST_CHECK(randomNeighbor != nullptr);
//	BOOST_CHECK(randomNeighbor->lastConnection == 1);
//
//
//	SystemAddress address;
//	address.FromString("124.0.0.12|2115");
//	manager->RemoveNeighbour(address);
//
//	BOOST_CHECK(manager->FindNeighbour(SystemAddress(string("124.0.0.12|2115").c_str())) == false);
//
//	inputNeighbours = "11223-127.0.0.1|21112-0;112356-124.0.0.12|2115-0;11223-127.0.0.1|21112-0;114545-129.0.0.2|45669-0;1129-189.168.2.1|44568-0;";
//	manager->AddNewNeighbours(inputNeighbours);
//	//sort 
//
//	/*int previous = 0, current = 0;
//
//	for (int index = 0; index < testingPeer->neighbors.size(); index++)
//	{
//	previous = index == 0 ? 0 : testingPeer->neighbors[index - 1].lastConnection;
//	current = testingPeer->neighbors[index].lastConnection;
//	BOOST_CHECK(previous <= current);
//	}
//
//	std::string output[2];*/
//}
//
//
//BOOST_AUTO_TEST_CASE(TestingObservableEventList)
//{
//	string testInputData = "";
//	/*ObservableEventsList<RadiancePoint>* testOEL = new Networking::ObservableEvents::ICObservableEventsList<RadiancePoint>(1,nullptr);*/
//	Networking::ObservableEvents::InsertEvent<>* testEvent = new Networking::ObservableEvents::InsertEvent<>(1, "0,1,0,0,0");
//	testEvent->GenerateUuids();
//}
//
//BOOST_AUTO_TEST_CASE(TestingVectorTimer)
//{
//	//one observable event
//	std::string inputString = "1,0,0,0,0";
//	int indexPosition = 1;
//	FixedVectorTimer test(1);
//	test.FromString(inputString);
//
//	std::string testOuptut = test.ToString();
//	BOOST_CHECK(testOuptut == inputString);
//
//	test.UpdatePeerTimer(5);
//	BOOST_CHECK(test.ToString() == "1,5,0,0,0");
//	//equality == true
//	BOOST_CHECK((test == test) == true);
//
//	std::string stringSecondInput = "1,2,3,1,0";
//	FixedVectorTimer secondTest(1);
//	secondTest.FromString(stringSecondInput);
//	bool equalityTest = (secondTest == test);
//	//equality should be false
//	BOOST_CHECK(equalityTest, false);
//	
//}
//
//#include "ObservableEvents/ObservableEvent.h"
//
//BOOST_AUTO_TEST_CASE(TestingObservableEvent)
//{
//	std::string inputString = "1,0,0,0,0";
//	int indexPosition = 1;
//	Network::VectorTimer* testVectorTimer = new FixedVectorTimer(1);
//	testVectorTimer->FromString(inputString);
//
//	Network::ObservableEvents::ObservableEvent<RadiancePoint>* testObservableEvent = new Networking::ObservableEvents::InsertEvent<RadiancePoint>(indexPosition, inputString);
//	
//	string tetsObservableEventOutput = testObservableEvent->ToString();
//	Network::ObservableEvents::ObservableEvent<RadiancePoint>* secondObservableEvent = new Networking::ObservableEvents::InsertEvent<RadiancePoint>();
//	secondObservableEvent->FromString(tetsObservableEventOutput);
//	cout << tetsObservableEventOutput << endl;
//	cout << secondObservableEvent->ToString() << endl;
//	BOOST_CHECK((secondObservableEvent == testObservableEvent) == true);
//
//	//BOOST_CHECK_EQUAL(tetsObservableEventOutput, secondObservableEvent->ToString());
//
//	system("pause");
//}
//
//BOOST_AUTO_TEST_CASE(TestingObservableEventsList)
//{
//	
//}



///-------------------------------------------------------------------------------------------------
// End of RayTracing.cpp
///-------------------------------------------------------------------------------------------------

